package com.github.xiaolyuh.base;

import com.github.xiaolyuh.configcenter.ConfigCenter;
import com.github.xiaolyuh.enums.CacheCodeEnum;
import com.github.xiaolyuh.exception.CacheException;
import com.github.xiaolyuh.utils.FastJSONHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Optional;

public class LocalBasicCacheManager implements BasicCacheManager {

    private static final Logger logger = LoggerFactory.getLogger(LocalBasicCacheManager.class);

    // 批量查询超时时间:100毫秒
    private static final Long BATCH_GET_WARN_TIME = 100L;

    private static final Long SIMPLE_GET_WARN_TIME = 10L;

    private com.google.common.cache.Cache<String, Optional<Object>> cache;

    public LocalBasicCacheManager(com.google.common.cache.Cache<String, Optional<Object>> cache) {
        this.cache = cache;
    }

    @Override
    public boolean set(String key, Object value, int expireTime) throws CacheException {
        try {
            if (!isCacheEnable()) {
                return true;
            }
            long startTime = System.currentTimeMillis();
            cache.put(key, Optional.ofNullable(value));
            if(logger.isDebugEnabled()){
                logger.debug("[cache]local cache set key={} value={}", key, FastJSONHelper.serialize(value));
            }
            long endTime = System.currentTimeMillis();
            long costTime = endTime - startTime;
            if (costTime > SIMPLE_GET_WARN_TIME) {
                logger.warn(String.format("[cache]local cache set cost time = %s ms,key=%s", costTime, key));
            }
            return Boolean.TRUE;
        } catch (Exception e) {
            logger.error("[cache]local cache set key error", e);
            throw new CacheException(CacheCodeEnum.FAIL.getCode(), e.getMessage());
        } catch (Throwable e) {
            logger.error("[cache]local cache set key error", e);
            throw new CacheException(CacheCodeEnum.FAIL);
        }
    }

    @Override
    public Object get(String key, Class clazz) throws CacheException {
        try {
            if (!isCacheEnable()) {
                return null;
            }
            long startTime = System.currentTimeMillis();
            Optional<Object> optional = cache.getIfPresent(key);
            Object value = optional != null ? optional.orElse(null) : null;
            if(logger.isDebugEnabled()){
                if(value != null){
                    logger.debug("[cache]local cache get key={} value={}", key, FastJSONHelper.serialize(value));
                }
            }
            long endTime = System.currentTimeMillis();
            long costTime = endTime - startTime;
            if (costTime > SIMPLE_GET_WARN_TIME) {
                logger.warn(String.format("[cache]local cache get cost time = %s ms,key=%s", costTime, key));
            }
            return value;
        } catch (Exception e) {
            logger.error("[cache]local cache get key error", e);
            throw new CacheException(CacheCodeEnum.FAIL.getCode(), e.getMessage());
        } catch (Throwable e) {
            logger.error("[cache]local cache get key error", e);
            throw new CacheException(CacheCodeEnum.FAIL);
        }
    }

    @Override
    public boolean isCacheEnable() {
        return ConfigCenter.allowLocalCache();
    }

    @Override
    public boolean delete(String key) throws CacheException {
        try {
            if (!isCacheEnable()) {
                return true;
            }
            cache.invalidate(key);
            if(logger.isDebugEnabled()){
                logger.debug("[cache]local cache delete key={}", key);
            }
            return Boolean.TRUE;
        } catch (Exception e) {
            logger.error("[cache]local cache delete key error", e);
            throw new CacheException(CacheCodeEnum.FAIL.getCode(), e.getMessage());
        } catch (Throwable e) {
            logger.error("[cache]local cache delete key error", e);
            throw new CacheException(CacheCodeEnum.FAIL);
        }
    }

    //*************************参数校验*************************

    private boolean checkArgs(List<String> keyList) {
        return keyList == null || keyList.isEmpty() || !isCacheEnable();
    }
}
